package com.hit.client.driver.netty.handler;

import cn.hutool.core.thread.ThreadUtil;
import com.hit.client.driver.netty.protocol.message.GfMessage;
import com.hit.client.driver.netty.router.GfMessageRouter;
import com.hit.client.driver.netty.strategy.GfMessageHandlerStrategy;
import com.hit.client.driver.util.GfToolkit;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
public class GfMessageHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // 处理接收到的消息，这里假设 msg 是你解码后的对象
        if (msg instanceof GfMessage message) {
            // 在这里处理消息，比如解析内容、处理业务逻辑等
            handleMessage(ctx, message);
        } else {
            log.warn("[gf]channel read unknown message type: {}", msg.getClass().getName());
        }
    }

    // 处理消息的业务逻辑
    private void handleMessage(ChannelHandlerContext ctx, GfMessage message) {
        // 根据命令进行分发
        ThreadUtil.execAsync(() -> {
            //异步分发给不同的 handler 用到反射,handler主线程不要做耗时间的操作,否则会阻塞线程
            byte[] data = message.getData();
            byte mainCmd = data[0];
            GfMessageHandlerStrategy strategy = GfMessageRouter.getHandlerStrategy(mainCmd);
            if (strategy != null) {
                strategy.handle(ctx, message);
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 处理异常
        log.error("[gf]channel exception caught in GfMessageHandler", cause);
        ctx.close();  // 关闭连接
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 当连接建立时的处理逻辑
        log.info("[gf]channel connection active: {}", ctx.channel().remoteAddress());
        super.channelActive(ctx);
        // 查询机器人编码
        byte[] data = new byte[]{(byte) 0x79, (byte) 0x12, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
        GfMessage gfMessage = new GfMessage(data);
        ctx.writeAndFlush(gfMessage);
        // 查询换行车编码
        byte[] data2 = new byte[]{(byte) 0x7C, (byte) 0x12, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
        GfMessage gfMessage2 = new GfMessage(data2);
        ctx.writeAndFlush(gfMessage2);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Iterator<Map.Entry<String, ChannelHandlerContext>> relayCtxIterator = GfToolkit.relayCtxMap.entrySet().iterator();
        while (relayCtxIterator.hasNext()) {
            Map.Entry<String, ChannelHandlerContext> entry = relayCtxIterator.next();
            if (Objects.equals(ctx, entry.getValue())) {
                relayCtxIterator.remove();
                log.info("[gf][{}] robot offline,clear relayCtx,channel connection inactive: {}", entry.getKey(), ctx.channel().remoteAddress());
                break;
            }
        }
        Iterator<Map.Entry<String, ChannelHandlerContext>> ctxIterator = GfToolkit.ctxMap.entrySet().iterator();
        while (ctxIterator.hasNext()) {
            Map.Entry<String, ChannelHandlerContext> entry = ctxIterator.next();
            if (Objects.equals(ctx, entry.getValue())) {
                ctxIterator.remove();
                log.info("[gf][{}] robot offline,clear ctx,channel connection inactive: {}", entry.getKey(), ctx.channel().remoteAddress());
                break;
            }
        }
        Iterator<Map.Entry<String, ChannelHandlerContext>> relayCtxOfCarIterator = GfToolkit.relayCtxOfCarMap.entrySet().iterator();
        while (relayCtxOfCarIterator.hasNext()) {
            Map.Entry<String, ChannelHandlerContext> entry = relayCtxOfCarIterator.next();
            if (Objects.equals(ctx, entry.getValue())) {
                relayCtxOfCarIterator.remove();
                log.info("[gf-car][{}] robot offline,clear relayCtxOfCar,channel connection inactive: {}", entry.getKey(), ctx.channel().remoteAddress());
                break;
            }
        }
        Iterator<Map.Entry<String, ChannelHandlerContext>> ctxOfCarIterator = GfToolkit.ctxOfCarMap.entrySet().iterator();
        while (ctxOfCarIterator.hasNext()) {
            Map.Entry<String, ChannelHandlerContext> entry = ctxOfCarIterator.next();
            if (Objects.equals(ctx, entry.getValue())) {
                ctxOfCarIterator.remove();
                log.info("[gf-car][{}] robot offline,clear ctxOfCar,channel connection inactive: {}", entry.getKey(), ctx.channel().remoteAddress());
                break;
            }
        }
        super.channelInactive(ctx);
    }
}
